﻿using IceCS.AsposeProd.Lic;
using System;
using System.Diagnostics;
using System.IO;

namespace IceCS.AsposeProd.Core.Services
{
    /// <summary>
    /// 生成的结构
    /// </summary>
    public class DocConvertService
    {
        /// <summary>
        /// 生成的html页面的文件名
        /// </summary>
        public string HtmlPageName { get; set; }

        /// <summary>
        /// 存放html页面的文件夹
        /// </summary>
        public string HtmlPageBaseFolderName { get; set; }

        /// <summary>
        /// 文档里面的其他附加存放路径和html页面访问附件的路径名
        /// </summary>
        public string HtmlPageAssetsFolderName { get; set; }

        /// <summary>
        /// 存放html页面的基础路径，默认在程序运行的文件夹下的 pages文件夹下
        /// </summary>
        public string GenPagesFolderPath { get; set; }

        public DocConvertService()
        {
            HtmlPageBaseFolderName = "pages";
            HtmlPageName = "index.html";
            HtmlPageAssetsFolderName = "assets";
            GenPagesFolderPath = Path.Combine(AppContext.BaseDirectory, HtmlPageBaseFolderName);

            AsposeUtil.CheckWordLic();
            AsposeUtil.CheckPptLic();
            AsposeUtil.CheckExcelLic();
            AsposeUtil.CheckPdfLic();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="genPagesPath">存放html页面的基础路径,推荐通过
        /// Path.Combine(AppContext.BaseDirectory,"pages")方式赋值</param>
        public DocConvertService(string genPagesPath) : base()
        {
            GenPagesFolderPath = genPagesPath;
        }
        #region 私有方法

        /// <summary>
        /// 创建文件夹
        /// </summary>
        /// <param name="filePath">文件夹路径</param>
        private void CreateFolder(string filePath)
        {
            if (Directory.Exists(filePath))
            {
                //Console.WriteLine($"存在目录：{filePath},删除目录");
                Directory.Delete(filePath, true);
            }
            //Console.WriteLine($"创建目录：{filePath}");
            Directory.CreateDirectory(filePath);
        }

        private string GetAssetsFolderPath(string fileName)
        {
            return Path.Combine(GenPagesFolderPath, fileName, HtmlPageAssetsFolderName);
        }

        private string GetIndexFilePath(string fileName)
        {
            return Path.Combine(GenPagesFolderPath, fileName, HtmlPageName);
        }

        /// <summary>
        /// 
        /// </summary>
        private class ImageSavingCallback : Aspose.Words.Saving.IImageSavingCallback
        {
            private string _assetsFolder;
            public ImageSavingCallback(string assetsFolder)
            {
                _assetsFolder = assetsFolder;
            }
            /// <summary>
            /// Word文件图片保存回调函数
            /// </summary>
            /// <param name="args"></param>
            public void ImageSaving(Aspose.Words.Saving.ImageSavingArgs args)
            {
                args.ImageFileName = $"word.{Guid.NewGuid():N}{Path.GetExtension(args.ImageFileName)}";
                Console.WriteLine($"保存图片文件：{args.ImageFileName}");
                args.ImageStream = File.OpenWrite(Path.Combine(_assetsFolder, args.ImageFileName));
            }
        }
        #endregion

        /// <summary>
        /// word 文档转换为 html 文件
        /// </summary>
        /// <param name="fileName">要生成的文件名</param>
        /// <param name="stream">文件流</param>
        /// <returns>生成的基于目标文件夹的路径</returns>
        public void ConvertWordToHtml1(string fileName, Stream stream)
        {
            //附件文件夹
            var assetsFolder = GetAssetsFolderPath(fileName);
            //html文件路径
            var indexFilePath = GetIndexFilePath(fileName);

            CreateFolder(assetsFolder);
            Aspose.Words.Document doc = null;
            try
            {
                doc = new Aspose.Words.Document(stream);
            }
            catch(Aspose.Words.UnsupportedFileFormatException ex)
            {
                Console.WriteLine("Word 文件无效或者 Word 文件被加密");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            if (doc == null)
            {
                throw new Exception("文件流解析失败");
            }

            var options = new Aspose.Words.Saving.HtmlSaveOptions(Aspose.Words.SaveFormat.Html)
            {

                //word 文档图片保存的物理目录(直接在回调函数里面通过流保存图片文件)
                ImagesFolder = assetsFolder,
                //指定html文档中访问图片的路径
                ImagesFolderAlias = HtmlPageAssetsFolderName,
                ImageSavingCallback = new ImageSavingCallback(assetsFolder),
                //是否缩放图片大小
                ScaleImageToShapeSize=false,
                //图片dpi
                ImageResolution=126
            };

            using var fs = File.OpenWrite(indexFilePath);
            var sw = Stopwatch.StartNew();
            Console.WriteLine($"开始执行转换 word：{fileName}，开始时间：{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffff}");
            doc.Save(fs, options);
            Console.WriteLine($"执行转换 word：{fileName} 完成，结束时间：{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffff}");
            sw.Stop();
            Console.WriteLine("耗时（毫秒）:"+sw.ElapsedMilliseconds);
        }

        /// <summary>
        /// pdf 文档转换为 html 文件（默认是图片嵌入到svg图片里面的模式）
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="stream">文件流</param>
        /// <returns>生成的基于目标文件夹的路径</returns>
        public void ConvertPdfToHtml1(string fileName, Stream stream)
        {
            //附件文件夹
            var assetsFolder = GetAssetsFolderPath(fileName);
            //html文件路径
            var indexFilePath = GetIndexFilePath(fileName);

            CreateFolder(assetsFolder);

            var pdf = new Aspose.Pdf.Document(stream);
            if (pdf == null)
            {
                throw new Exception("Pdf 文件无效或者 Pdf 文件被加密");
            }
            var options = new Aspose.Pdf.HtmlSaveOptions()
            {
                FontEncodingStrategy = Aspose.Pdf.HtmlSaveOptions.FontEncodingRules.Default,
                //文档类型为 h5
                DocumentType = Aspose.Pdf.HtmlDocumentType.Html5,
                //光栅图像保存模式,png图片嵌入svg图片渲染
                RasterImagesSavingMode = Aspose.Pdf.HtmlSaveOptions.RasterImagesSavingModes.AsPngImagesEmbeddedIntoSvg,
                //把图片保存为pdf页的背景图，然后通过分隔显示
                //RasterImagesSavingMode = Aspose.Pdf.HtmlSaveOptions.RasterImagesSavingModes.AsEmbeddedPartsOfPngPageBackground,
                //此模式需要考虑svg里面引用的png图片路径
                //RasterImagesSavingMode = Aspose.Pdf.HtmlSaveOptions.RasterImagesSavingModes.AsExternalPngFilesReferencedViaSvg,
                //保存水印
                SaveShadowedTextsAsTransparentTexts = true,
                //保存水印
                SaveTransparentTexts = true,
                //生成的html只保留 body
                HtmlMarkupGenerationMode = Aspose.Pdf.HtmlSaveOptions.HtmlMarkupGenerationModes.WriteAllHtml,
                //存到一个文件里面去
                SplitIntoPages = false,
                //css内嵌
                PartsEmbeddingMode = Aspose.Pdf.HtmlSaveOptions.PartsEmbeddingModes.EmbedCssOnly,

                //自定义所有资源保存策略
                CustomResourceSavingStrategy = new Aspose.Pdf.HtmlSaveOptions.ResourceSavingStrategy(resourceSavingInfo =>
                {
                    var extName = Path.GetExtension(resourceSavingInfo.SupposedFileName);
                    var resName = $"pdf.{Guid.NewGuid():N}{extName}";
                    //保存的资源路径
                    var fileName = Path.Combine(assetsFolder, resName);
                    Console.WriteLine($"保存资源 {fileName}");
                    using var fs = File.OpenWrite(fileName);
                    resourceSavingInfo.ContentStream.CopyTo(fs);

                    //html文档中相对的路径
                    var path = $"{HtmlPageAssetsFolderName}/{resName}";
                    return path;
                })

            };
            using var fs = File.OpenWrite(indexFilePath);
            var sw = Stopwatch.StartNew();
            Console.WriteLine($"开始执行转换 pdf：{fileName}，开始时间：{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffff}");
            pdf.Save(fs, options);
            Console.WriteLine($"执行转换 pdf：{fileName} 完成，结束时间：{DateTime.Now:yyyy-MM-dd HH:mm:ss.ffff}");
            sw.Stop();
            Console.WriteLine("耗时（毫秒）:" + sw.ElapsedMilliseconds);
        }

        /// <summary>
        /// pdf 文档转换为 html 文件(通过pdf文件另存为word文件模式，然后word文件转换为html)(效果很不好)
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <param name="stream">文件流</param>
        /// <returns>生成的基于目标文件夹的路径</returns>
        public void ConvertPdfToHtml2(string fileName, Stream stream)
        {
            var pdf = new Aspose.Pdf.Document(stream);
            if (pdf == null)
            {
                throw new Exception("Pdf 文件无效或者 Pdf 文件被加密");
            }
            //基础文件夹
            var baseFolder = Path.Combine(GenPagesFolderPath, fileName);
            CreateFolder(baseFolder);
            using var fs = new MemoryStream();
            Console.WriteLine($"开始执行转换 pdf：{fileName} 转换为 word 文件，开始时间：{DateTime.Now}");
            pdf.Save(fs, Aspose.Pdf.SaveFormat.DocX);
            Console.WriteLine($"执行转换 pdf：{fileName} 转换为 word 文件完成，结束时间：{DateTime.Now}");
            ConvertWordToHtml1(fileName, fs);
            using var wordFs = File.OpenWrite(Path.Combine(baseFolder, fileName.Replace(".pdf", ".docx")));
            fs.Seek(0, SeekOrigin.Begin);
            fs.CopyTo(wordFs);
        }

        /// <summary>
        /// 转换文本内容为word文件流
        /// </summary>
        /// <param name="fileContent">文本内容</param>
        /// <returns></returns>
        public Stream ConvertHtmlToWord(string fileContent)
        {
            var ms = new MemoryStream(capacity: 4096);
            var doc = new Aspose.Words.Document();
            var builder = new Aspose.Words.DocumentBuilder(doc);
            builder.InsertHtml(fileContent);
            doc.Save(ms, Aspose.Words.SaveFormat.Docx);
            ms.Seek(0L, SeekOrigin.Begin);
            return ms;
        }

        /// <summary>
        /// 转换文本内容为pdf文件流
        /// </summary>
        /// <param name="fileContent">文本内容</param>
        /// <returns></returns>
        public Stream ConvertHtmlToPDF(string fileContent)
        {
            var ms = new MemoryStream(capacity: 4096);
            var doc = new Aspose.Words.Document();
            var builder = new Aspose.Words.DocumentBuilder(doc);
            builder.InsertHtml(fileContent);
            doc.Save(ms, Aspose.Words.SaveFormat.Pdf);
            ms.Seek(0L, SeekOrigin.Begin);
            return ms;
        }
    }
}
